#include "precompiled.h"
#include "windowproxy.h"

using namespace Gui;

class Gui::WindowProxyPrivate{
public:
    WindowProxyPrivate():
            popupShown(false),
            currentPopup(0),
            shadowGap(5),
            frameAlpha(20)
    {}

    ~WindowProxyPrivate() {}
    QTimeLine *timeLine;
    bool popupShown;
    QGraphicsItem *currentPopup;
    int shadowGap;
    int frameAlpha;

};

WindowProxy::WindowProxy(QGraphicsItem *parent/* = 0*/, Qt::WindowFlags flag/* = 0*/) :
        QGraphicsProxyWidget(parent, flag), O_PRIVATE_CREATE(WindowProxy)
{
    O_D(WindowProxy);
    d->timeLine = new QTimeLine(250, this);
    connect(d->timeLine, SIGNAL(valueChanged(qreal)),this, SLOT(updateStep(qreal)));
    connect(d->timeLine, SIGNAL(stateChanged(QTimeLine::State)), this, SLOT(stateChanged(QTimeLine::State)));
}

WindowProxy::~WindowProxy()
{
    O_PRIVATE_DELETE;
}

QRectF WindowProxy::boundingRect()const
{
    O_D(const WindowProxy);
    return QGraphicsProxyWidget::boundingRect().adjusted(-d->shadowGap, -d->shadowGap, d->shadowGap, d->shadowGap);
}

void WindowProxy::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    O_D(WindowProxy);


    QPainterPath path;
    QRectF r = rect();

    QRectF left(r.left() - d->shadowGap, r.top(), d->shadowGap, r.height() + d->shadowGap);
    if (left.intersects(option->exposedRect)){
        path.addRect(left);
    }

    QRectF right(r.right(), r.top() - d->shadowGap, d->shadowGap, r.height() + d->shadowGap);
    if (right.intersects(option->exposedRect)){
        path.addRect(right);
    }

    QRectF top(r.left() - d->shadowGap, r.top() - d->shadowGap, r.width() + d->shadowGap, d->shadowGap);
    if (top.intersects(option->exposedRect)){
        path.addRect(top);
    }

    QRectF bottom(r.left(), r.bottom(), r.width() + d->shadowGap, d->shadowGap);
    if (bottom.intersects(option->exposedRect)){
        path.addRect(bottom);
    }

    if (!path.isEmpty()){
        const QColor color(255, 255, 255, d->frameAlpha);
        painter->setBrush(color);
        painter->setPen(Qt::NoPen);
        painter->drawPath(path);
    }

   // QGraphicsProxyWidget::paintWindowFrame(painter, option, widget);
}

QVariant WindowProxy::itemChange(GraphicsItemChange change, const QVariant &value)
{
    O_D(WindowProxy);
    if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
        if (change == ItemChildAddedChange) {
            d->currentPopup = qVariantValue<QGraphicsItem *>(value);
            d->currentPopup->setCacheMode(ItemCoordinateCache);
            if (scene()){
                d->currentPopup->installSceneEventFilter(this);
            }
        } else if (scene()) {
            d->currentPopup->removeSceneEventFilter(this);
            d->currentPopup = 0;
        }
    } else if (d->currentPopup && change == ItemSceneHasChanged) {
        d->currentPopup->installSceneEventFilter(this);
    }
    return QGraphicsProxyWidget::itemChange(change, value);
}

void WindowProxy::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    O_D(WindowProxy);
    QGraphicsProxyWidget::hoverEnterEvent(event);
    scene()->setActiveWindow(this);
    if (d->timeLine->currentValue() != 1){
        hoverIn();
    }
}

void WindowProxy::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    O_D(WindowProxy);
    QGraphicsProxyWidget::hoverLeaveEvent(event);
    if (!d->popupShown && (d->timeLine->direction() != QTimeLine::Backward || d->timeLine->currentValue() != 0)){
        hoverOut();
    }
}

bool WindowProxy::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
    O_D(WindowProxy);
    if (watched->isWindow() && (event->type() == QEvent::UngrabMouse || event->type() == QEvent::GrabMouse)) {
        d->popupShown = watched->isVisible();
        if (!d->popupShown && !isUnderMouse()){
            hoverOut();
        }
    }
    return QGraphicsProxyWidget::sceneEventFilter(watched, event);
}

void WindowProxy::updateStep(qreal step)
{
    QRectF r = boundingRect();
    O_D(WindowProxy);
    d->frameAlpha = 20 + (60 * step);
    qDebug() << "step=" << step;
    update();
//    setTransform(QTransform()
//                 .translate(r.width() / 2, r.height() / 2)
//                 .rotate(step * 30, Qt::XAxis)
//                 .rotate(step * 10, Qt::YAxis)
//                 .rotate(step * 5, Qt::ZAxis)
//                 .scale(1 + 1.5 * step, 1 + 1.5 * step)
//                 .translate(-r.width() / 2, -r.height() / 2)
//                 );
}

void WindowProxy::stateChanged(QTimeLine::State state)
{
    O_D(WindowProxy);
    if (state == QTimeLine::Running) {
        if (d->timeLine->direction() == QTimeLine::Forward)
            setCacheMode(ItemCoordinateCache);
    } else if (state == QTimeLine::NotRunning) {
        if (d->timeLine->direction() == QTimeLine::Backward)
            setCacheMode(DeviceCoordinateCache);
    }
}

void WindowProxy::hoverIn()
{
    O_D(WindowProxy);
    if (d->timeLine->direction() != QTimeLine::Forward)
        d->timeLine->setDirection(QTimeLine::Forward);
    if (d->timeLine->state() == QTimeLine::NotRunning)
        d->timeLine->start();
}

void WindowProxy::hoverOut()
{
    O_D(WindowProxy);
    if (d->timeLine->direction() != QTimeLine::Backward)
        d->timeLine->setDirection(QTimeLine::Backward);
    if (d->timeLine->state() == QTimeLine::NotRunning)
        d->timeLine->start();
}
